package soccerBet.project.betfair.handler;


import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.axis2.transport.http.HttpTransportProperties.ProxyProperties;

import soccerBet.project.betfair.global.BFGlobalServiceStub;
import soccerBet.project.betfair.global.BFGlobalServiceStub.EventType;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetActiveEventTypes;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEventTypesReq;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEventTypesResp;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEvents;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEventsErrorEnum;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEventsReq;
import soccerBet.project.betfair.global.BFGlobalServiceStub.GetEventsResp;
import soccerBet.project.betfair.global.BFGlobalServiceStub.Login;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LoginErrorEnum;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LoginReq;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LoginResp;
import soccerBet.project.betfair.global.BFGlobalServiceStub.Logout;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LogoutErrorEnum;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LogoutReq;
import soccerBet.project.betfair.global.BFGlobalServiceStub.LogoutResp;
import soccerBet.project.betfair.util.APIContext;
import soccerBet.project.utils.ManageMethods;



public class GlobalAPI {

    private static BFGlobalServiceStub stub;
    
	// Lasy load the Global service stub generated by Apache Axis.
	// This stub is used to make all requests to the Betfair Global API
    // The global API is generally used for account management features
	private static BFGlobalServiceStub getStub() throws Exception {
		if (stub == null)
		{
			stub = new BFGlobalServiceStub("https://api.betfair.com/global/v3/BFGlobalService");

			// You may set up the connection parameters of the stub here if necessary
	        // For example: Wait 20 seconds for a response from the API
			stub._getServiceClient().getOptions().setTimeOutInMilliSeconds(20 * 1000);
			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.MC_ACCEPT_GZIP, "true");
			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.MC_GZIP_RESPONSE, "true");		
			//ADICIONEI ESTAS 2 LINHAS
//			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTO_RELEASE_CONNECTION, true);
//			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.CACHED_HTTP_CLIENT,stub);
//			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER,true);
//			stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.REUSE_HTTP_CLIENT,true);
		}
		return stub;
	}
	
	// Get the request header to add to the request
	private static soccerBet.project.betfair.global.BFGlobalServiceStub.APIRequestHeader getHeader(APIContext context) {
		soccerBet.project.betfair.global.BFGlobalServiceStub.APIRequestHeader header = new soccerBet.project.betfair.global.BFGlobalServiceStub.APIRequestHeader();
        // The header must have the session token attached.
        header.setSessionToken(context.getToken());
        return header;
	}
	
	// Save the data from the request header into the context
	private static void setHeaderDataToContext(APIContext context, soccerBet.project.betfair.global.BFGlobalServiceStub.APIResponseHeader apiResponseHeader) {
		context.setToken(apiResponseHeader.getSessionToken()); // May be updated in each call.
		context.setLastCall(apiResponseHeader.getTimestamp().getTime());
	}

	// Fire a Web services login request
	public static void login(APIContext context, String username, String password) throws Exception {
		
		if(ManageMethods.verificaCallsPossiveis(context.getUsage(),"login")==true){
			// Create a login request object
	        LoginReq request = new LoginReq();
	        // Set the parameters you wish to pass the the API
	        request.setUsername(username);
	        request.setPassword(password);
	        request.setProductId(82); // 82 is the standard Free Access API
	        request.setIpAddress(""); // Does not need to be set, but may not be null so use an empty string.
	        // Create the Login message and attach the request to it.
	        Login msg = new Login();
	        msg.setRequest(request);
	        // Send the request to the Betfair Service.
	        LoginResp resp = getStub().login(msg).getResult();
	        context.getUsage().addCall("login");
	        // Check the response code, and throw and exception if the call failed
	        if (resp.getErrorCode() != LoginErrorEnum.OK)
	        {
	        	throw new IllegalArgumentException("Failed to log in: "+resp.getErrorCode() + " Minor Error:"+resp.getMinorErrorCode()+ " Header Error:"+resp.getHeader().getErrorCode());
	        }
	
	        // Transfer the response data back to the API context
	        setHeaderDataToContext(context, resp.getHeader());
		}
	}
	

	// Get the active event types within the system (on both exchanges)
	public static EventType[] getActiveEventTypes(APIContext context) throws Exception {
		// Create a request object
        GetEventTypesReq request = new GetEventTypesReq();
        request.setHeader(getHeader(context));
        
        // Create the GetActiveEventTypes message and attach the request to it.
        GetActiveEventTypes msg = new GetActiveEventTypes ();
        msg.setRequest(request);
        
        // Send the request to the Betfair Service.
        GetEventTypesResp resp = getStub().getActiveEventTypes(msg).getResult();
        context.getUsage().addCall("getActiveEventTypes");
        
        // Check the response code, and throw and exception if the call failed
        if (resp.getErrorCode() != GetEventsErrorEnum.OK)
        {
        	throw new IllegalArgumentException("Failed to retrieve active event types: "+resp.getErrorCode() + " Minor Error:"+resp.getMinorErrorCode()+ " Header Error:"+resp.getHeader().getErrorCode());
        }

        // Transfer the response data back to the API context
        setHeaderDataToContext(context, resp.getHeader());

        return resp.getEventTypeItems().getEventType();
	}
	
	// Get the markets available for the event specified
	public static GetEventsResp getEvents(APIContext context, int eventId) throws Exception {
		// Create a request object
        GetEventsReq request = new GetEventsReq();
        request.setHeader(getHeader(context));
        
        // Set the parameter
        request.setEventParentId(eventId);

        // Create the GetActiveEventTypes message and attach the request to it.
        GetEvents msg = new GetEvents();
        msg.setRequest(request);
        
        // Send the request to the Betfair Service.
        GetEventsResp resp = getStub().getEvents(msg).getResult();
        context.getUsage().addCall("getEvents");
        
        // Check the response code, and throw and exception if the call failed
        if (resp.getErrorCode() != GetEventsErrorEnum.OK)
        {
        	throw new IllegalArgumentException("Failed to retrieve events: "+resp.getErrorCode() + " Minor Error:"+resp.getMinorErrorCode()+ " Header Error:"+resp.getHeader().getErrorCode());
        }

        // Transfer the response data back to the API context
        setHeaderDataToContext(context, resp.getHeader());
      
        return resp;
	}
	
	// Fire a Web services logout request
	public static void logout(APIContext context) throws Exception {
		// Create a request object
        LogoutReq request = new LogoutReq();
        request.setHeader(getHeader(context));

        // Create the Logout message and attach the request to it.
        Logout msg = new Logout();
        msg.setRequest(request);
        
        // Send the request to the Betfair Service.
        LogoutResp resp = getStub().logout(msg).getResult();
        context.getUsage().addCall("logout");
       
        // Check the response code, and throw and exception if the call failed
        if (resp.getErrorCode() != LogoutErrorEnum.OK)
        {
        	throw new IllegalArgumentException("Failed to log out: "+resp.getErrorCode() + " Minor Error:"+resp.getMinorErrorCode()+ " Header Error:"+resp.getHeader().getErrorCode());
        }
        
        setHeaderDataToContext(context, resp.getHeader());
	}
	
}
